package com.ctg.behavior.calc.impala.transfer.event;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.ctg.behavior.calc.common.CtCalcDate;
import com.ctg.behavior.calc.common.CtSQLParam;
import com.ctg.behavior.calc.impala.builder.event.CtEventMeasureDateScopeBuilder;
import com.ctg.behavior.calc.impala.builder.event.CtEventMeasureGroupByBuilder;
import com.ctg.behavior.calc.impala.builder.event.CtEventMeasureSelectBuilder;
import com.ctg.behavior.calc.impala.report.event.CtCalcEventMeasureReport;
import com.ctg.behavior.calc.impala.transfer.CtFilterTransfer;
import com.ctg.behavior.calc.utils.CtCalcDaysUtils;
import com.ctg.behavior.calc.utils.CtCalcSQLUtils;
import com.ctg.behavior.client.impala.utils.CtCalcSQLParserUtils;
import com.ctg.behavior.common.calc.CtCalc;
import com.ctg.behavior.common.calc.CtCalcFilter;
import com.ctg.behavior.common.consts.CtCalcConsts;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CtEventMeasureTransfer extends CtFilterTransfer {

	@Autowired
	private CtEventMeasureSelectBuilder selectBuilder;
	@Autowired
	private CtEventMeasureDateScopeBuilder dateScopeBuilder;
	@Autowired
	private CtEventMeasureGroupByBuilder groupByBuilder;

	@Override
	public String doTransfer(CtCalc calcObject, CtSQLParam sqlParam) {
		if (!(calcObject instanceof CtCalcEventMeasureReport)) {
			log.warn("calcObject is not CtCalcEventMeasureReport, class={}", calcObject.getClass());
			return "";
		}
		CtCalcEventMeasureReport measure = (CtCalcEventMeasureReport) calcObject;
		log.info("measure={}", JSON.toJSONString(measure));

		StringBuilder impalaSQL = new StringBuilder();

		// 1.当天的数据存放在a_event_kudu_{appId}表中, 称为实时数据
		// 2.除当天的数据，其它数据均存放在a_event_parquet_{appId}表中, 称为历史数据
		CtCalcDate calcDate = measure.getCaclDate();
		if (CtCalcConsts.UNIT_TYPE_MINUTE.equals(measure.getUnit())
				|| CtCalcConsts.UNIT_TYPE_HOUR.equals(measure.getUnit()) ) {
			// 在按天(或按小时或按分钟)查询的模式下，要判断是否查询的是当天的数据，若是则从实时数据中查询
			Boolean isRealTimeData = CtCalcDaysUtils.isContainToday(calcDate);
			impalaSQL.append(this.transferByDataType(isRealTimeData, measure, sqlParam, true));
		} else if (CtCalcConsts.UNIT_TYPE_DAY.equals(measure.getUnit())
				|| CtCalcConsts.UNIT_TYPE_WEEK.equals(measure.getUnit())
				|| CtCalcConsts.UNIT_TYPE_MONTH.equals(measure.getUnit()) ) {
			Boolean hasRealTimeData = CtCalcDaysUtils.isContainToday(calcDate);
			if (hasRealTimeData) {
				String realtimeImpalaSQL = this.transferByDataType(true, measure, sqlParam, false);
				String historyImpalaSQL = this.transferByDataType(false, measure, sqlParam, false);
				List<String> sqlSelectFields = CtCalcSQLParserUtils.fetchSelectFields(historyImpalaSQL);
				sqlSelectFields.remove("total");
				impalaSQL.append(" SELECT ");
				for (String selectField : sqlSelectFields) {
					impalaSQL.append(selectField).append(" AS ").append(selectField);
					impalaSQL.append(" , ");
				}
				impalaSQL.append(" SUM(total) AS total ");
				impalaSQL.append(" FROM ( ");
				impalaSQL.append(realtimeImpalaSQL);
				impalaSQL.append(" UNION ");
				impalaSQL.append(historyImpalaSQL);
				impalaSQL.append(" ) T0 ");
				String groupBySQL = CtCalcSQLParserUtils.fetchGroupBy(historyImpalaSQL);
				impalaSQL.append(groupBySQL);
				impalaSQL.append(" ORDER BY byTime ASC ");
			} else {
				impalaSQL.append(this.transferByDataType(false, measure, sqlParam, true));
			}
		}
		
		impalaSQL.append(" LIMIT 1000 ");

		return impalaSQL.toString();
	}

	private String transferByDataType(Boolean isRealTimeData, CtCalcEventMeasureReport measure, CtSQLParam sqlParam, Boolean needOrderBy) {

		StringBuilder impalaSQL = new StringBuilder();

		// 1. SELECT 部分：
		{
			String selectPartSQL = selectBuilder.doBuilder(measure);
			impalaSQL.append(selectPartSQL).append(" ");
		}
		// 2. 表关联
		{
			// 2.1 根据APP_ID来决定查询哪个表
			if (isRealTimeData) {
				impalaSQL.append(" FROM a_event_kudu_").append(measure.getAppId()).append(" WHERE 1=1 ");
			} else {
				impalaSQL.append(" FROM a_event_parquet_").append(measure.getAppId()).append(" WHERE 1=1 ");
			}
		}
		// 3. 查询条件 - measure中的筛选条件(filter)
		{
			CtCalcFilter filter = measure.getFilter();
			String filterSQL = super.doTransfer(filter, sqlParam);
			if (!CtCalcSQLUtils.isEmptyCondtions(filterSQL)) {
				impalaSQL.append(" AND ").append(filterSQL);
			}
			log.info("measure-filter:[{}]", filterSQL);
		}
		// 4. 查询条件 - 全局过滤条件
		{
			CtCalcFilter filter = measure.getGlobalFilter();
			String filterSQL = super.doTransfer(filter, sqlParam);
			if (!CtCalcSQLUtils.isEmptyCondtions(filterSQL)) {
				impalaSQL.append(" AND ").append(filterSQL);
			}
			log.info("measure-Globalfilter:[{}]", filterSQL);
		}
		// 5. 查询条件 - 时间范围(也要考虑Measure中的aggregator含义)
		{
			String dateScopePartSQL = dateScopeBuilder.doBuilder(measure.getCaclDate(), measure);
			if (!StringUtils.isEmpty(dateScopePartSQL)) {
				impalaSQL.append(" AND ").append(dateScopePartSQL);
			}
			log.info("measure-dateScope:[{}]", dateScopePartSQL);
		}
		// 6. 分组(group by) - (要考虑Measure中的aggregator含义)
		{
			String groupByPartSQL = groupByBuilder.doBuilder(measure);
			impalaSQL.append(groupByPartSQL);
		}
		//
		if(needOrderBy) {
			impalaSQL.append(" ORDER BY byTime ASC ");
		}

		return impalaSQL.toString();
	}

}
